﻿using SmartPlant.Model.Biz;
using SmartPlant.WinCore;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq.Expressions;
using Telerik.Windows.Controls;

namespace SmartPlant.Model.UI
{
    public class TreeNodeModelList : ObservableCollection<TreeNodeModel>
    {
        public event PropertyChangedEventHandler SelectChanged;

        private bool isUpdating;

        public bool IsUpdating
        {
            get { return isUpdating; }
            set
            {
                isUpdating = value;
                OnPropertyChanged(new PropertyChangedEventArgs("IsUpdating"));
            }
        }

        public TreeNodeModelList()
        {
            this.CollectionChanged += TreeNodeModelList_CollectionChanged;
        }

        public void BeginUpdate()
        {
            IsUpdating = true;
        }

        public void EndUpdate()
        {
            IsUpdating = false;
        }

        /// <summary>
        /// 根据条件查询需要的结果。
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public IList<TreeNodeModel> FindNodes(Expression<Func<TreeNodeModel, bool>> predicate)
        {
            var result = new List<TreeNodeModel>();
            var queryResult = this.AsQueryable().Where(predicate);
            if (queryResult != null && queryResult.Any())
                result.AddRange(queryResult);
            foreach (TreeNodeModel node in this)
            {
                var list = QuerySubNode(node.Nodes, predicate);
                if (list != null && list.Count > 0)
                {
                    result.AddRange(list);
                }
            }
            return result;
        }

        private IList<TreeNodeModel> QuerySubNode(IList<TreeNodeModel> subNodes, Expression<Func<TreeNodeModel, bool>> predicate)
        {
            var result = new List<TreeNodeModel>();
            var queryResult = subNodes.AsQueryable().Where(predicate);
            if (queryResult != null && queryResult.Any())
                result.AddRange(queryResult);
            foreach (TreeNodeModel node in subNodes)
            {
                if (node.Nodes != null && node.Nodes.Count > 0)
                {
                    var list = QuerySubNode(node.Nodes, predicate);
                    if (list != null && list.Count > 0)
                    {
                        result.AddRange(list);
                    }
                }
            }
            return result;
        }

        private void TreeNodeModelList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            SelectChanged?.Invoke(sender, new PropertyChangedEventArgs(""));
        }

        internal void OnSelectChanged(PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsSelected" && !IsUpdating)
                SelectChanged?.Invoke(this, e);
        }

        protected override void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);

            if (e.PropertyName == "IsSelected" && !IsUpdating)
                SelectChanged?.Invoke(this, e);
        }
    }

    public class TreeNodeModel : ViewModelBase, ITreeNodeModel
    {
        protected TreeNodeModel _parentItem = null;
        protected TreeNodeModelList _root = null;
        private PlantAreaUnit _unit = null;
        /// <summary>
        /// 通过构造函数来弄成tree结构
        /// </summary>
        /// <param name="root"></param>
        /// <param name="parentItem"></param>
        public TreeNodeModel(TreeNodeModelList root, TreeNodeModel parentItem)
        {
            _parentItem = parentItem;
            _root = root;
        }
        /// <summary>
        /// 自带一个空白子节点的Node
        /// </summary>
        /// <param name="root"></param>
        /// <param name="parentItem"></param>
        /// <param name="WithBlankNode">是否带一个空的</param>
        public TreeNodeModel(TreeNodeModelList root, TreeNodeModel parentItem, bool WithBlankNode)
        {
            _parentItem = parentItem;
            _root = root;

            if (WithBlankNode)
            {
                var blankNode = new TreeNodeModel(_root, _parentItem)
                {
                    NodeType = TreeNodeType.Blank
                };
                this.Nodes.Add(blankNode);
            }
        }
        public TreeNodeModel Parent
        {
            get => _parentItem;
            private set { }
        }

        private TreeNodeModelList _nodes = new();

        public TreeNodeModelList Nodes
        {
            get { return _nodes; }
            set
            {
                _nodes = value;
                RaisePropertyChanged();
            }
        }

        public PlantAreaUnit Unit
        {
            get { return _unit; }
            set
            {
                _unit = value;
                RaisePropertyChanged();
            }
        }

        private string _id;
        /// <summary>
        /// id，如cmpntid，plantid等
        /// </summary>
        public string Id
        {
            get { return _id; }
            set
            {
                this._id = value;
                OnPropertyChanged(nameof(Id));
            }
        }

        private string _nodeName = "空";
        /// <summary>
        /// 节点名字(默认就是叫“空”）
        /// </summary>
        public string NodeName
        {
            get { return _nodeName; }
            set
            {
                this._nodeName = value;
                OnPropertyChanged(nameof(NodeName));
            }
        }

        private string _iconGlyph;

        public string IconGlyph
        {
            get { return _iconGlyph; }
            set
            {
                this._iconGlyph = value;
                OnPropertyChanged(nameof(IconGlyph));
            }
        }

        private TreeNodeType _nodeType;
        /// <summary>
        /// 自定义的节点类型，可以决定一个默认的图标
        /// </summary>
        public TreeNodeType NodeType
        {
            get { return _nodeType; }
            set
            {
                this._nodeType = value;
                switch (value)
                {
                    case TreeNodeType.Panel_DCSFolder:
                        _iconGlyph = "&#xe67c;";
                        break;
                    case TreeNodeType.PanelFolder:
                    case TreeNodeType.Panel_JBFolder:
                    case TreeNodeType.Panel_MRFolder:
                        _iconGlyph = "&#xe67f;";
                        break;
                    case TreeNodeType.Panel_DPFolder:
                        _iconGlyph = "&#xe67b;";
                        break;

                    case TreeNodeType.NoDeviceCableFolder:
                    case TreeNodeType.DeviceCableFolder:
                    case TreeNodeType.CableFolder:
                    case TreeNodeType.Cable:
                        _iconGlyph = "&#xe819;";
                        break;
                    case TreeNodeType.Plant:
                        _iconGlyph = "&#xe034;";
                        break;

                    case TreeNodeType.Area:
                        _iconGlyph = "&#xe66f;";
                        break;

                    case TreeNodeType.Unit:
                        _iconGlyph = "&#xe675;";
                        break;

                    case TreeNodeType.Loop:
                        _iconGlyph = "&#xe10e;";
                        break;

                    case TreeNodeType.Instrument:
                        _iconGlyph = "&#xe107;";
                        break;

                    case TreeNodeType.LoopFolder:
                    case TreeNodeType.InstrumentFolder:
                        _iconGlyph = "&#xe900;";
                        break;
                    case TreeNodeType.PIDFolder:
                    case TreeNodeType.InstrumentDoc_pd:
                        _iconGlyph = "&#xe661;";
                        break;
                    case TreeNodeType.InstrumentDoc_spec:
                        _iconGlyph = "&#xe64f;";
                        break;

                    case TreeNodeType.HookUpFolder:
                        _iconGlyph = "&#xe13c;";
                        break;

                    case TreeNodeType.Line:
                    case TreeNodeType.LineFolder:
                        _iconGlyph = "&#xe14a;";
                        break;

                    case TreeNodeType.Equip:
                    case TreeNodeType.EquipFolder:
                        _iconGlyph = "&#xe802;";
                        break;
                    default:
                        break;
                }
                OnPropertyChanged(nameof(NodeType));
            }
        }

        private bool _isExpanded;

        public bool IsExpanded
        {
            get { return _isExpanded; }
            set
            {
                this._isExpanded = value;
                OnPropertyChanged(nameof(IsExpanded));
            }
        }

        private bool reentrancyCheck = false;
        protected bool? _isSelected = false;
        /// <summary>
        ///  大概率会绑定到xaml里的IsChecked上
        /// </summary>
        public virtual bool? IsSelected
        {
            get { return _isSelected; }
            set
            {
                if (this._isSelected != value)
                {
                    var updating = _root.IsUpdating;
                    _root.BeginUpdate();
                    if (reentrancyCheck)
                        return;
                    this.reentrancyCheck = true;
                    this._isSelected = value;

                    this.UpdateCheckState();
                    OnPropertyChanged(nameof(IsSelected));
                    this.reentrancyCheck = false;
                    if (!updating)
                        _root.EndUpdate();
                    _root.OnSelectChanged(new PropertyChangedEventArgs(nameof(IsSelected)));
                }
            }
        }

        private bool _isEditable;

        public bool IsEditable
        {
            get { return _isEditable; }
            set
            {
                this._isEditable = value;
                OnPropertyChanged(nameof(IsEditable));
            }
        }

        private void UpdateCheckState()
        {
            if (this.Nodes.Count != 0)
            {
                this.UpdateChildrenCheckState();
            }
            if (this._parentItem != null)
            {
                bool? parentIsChecked = this._parentItem.DetermineCheckState();
                this._parentItem.IsSelected = parentIsChecked;
            }
        }

        private void UpdateChildrenCheckState()
        {
            foreach (var item in this.Nodes)
            {
                if (this.IsSelected != null)
                {
                    item.IsSelected = this.IsSelected;
                }
            }
        }

        private bool? DetermineCheckState()
        {
            bool allChildrenChecked = this.Nodes.Count(x => x.IsSelected == true) == this.Nodes.Count;
            if (allChildrenChecked)
            {
                return true;
            }

            bool allChildrenUnchecked = this.Nodes.Count(x => x.IsSelected == false) == this.Nodes.Count;
            if (allChildrenUnchecked)
            {
                return false;
            }

            return null;
        }
    }

    public class TreeNodeRadiolModel : TreeNodeModel
    {
        /// <summary>
        /// 通过构造函数来弄成tree结构
        /// </summary>
        /// <param name="root"></param>
        /// <param name="parentItem"></param>
        public TreeNodeRadiolModel(TreeNodeModelList root, TreeNodeModel parentItem) : base(root, parentItem)
        {

        }

        public override bool? IsSelected
        {
            get { return _isSelected; }
            set
            {
                this._isSelected = value;
                OnPropertyChanged(nameof(IsSelected));
                _root.OnSelectChanged(new PropertyChangedEventArgs(nameof(IsSelected)));
            }
        }
    }
}